﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Core;
using Silvermoon.OpenGL.Native;
using Silvermoon.OpenGL.Native.Vectors;
using System.Drawing;

namespace Silvermoon.Shapes
{
    /// <summary>
    /// Shape of a rectangle border with configurable border size and color.
    /// </summary>
    public class BorderShape : Shape
    {
        #region fields
        private Color color;
        private Vector2s[] vectors;
        private Size vectorSize;

        #endregion
        #region ctor

        public BorderShape()
            : base()
        {
            BorderSize = 2;
            Color = new GlColor(255, 255, 255, 255);
            Edges = BorderEdge.All;
        }

        public BorderShape(int borderSize, GlColor color)
            : this()
        {
            this.BorderSize = borderSize;
            this.Color = color;
        }

        public BorderShape(int borderSize, Color color)
            : this()
        {
            this.BorderSize = borderSize;
            this.Color = color;
        }

        #endregion
        #region props

        public bool UseTextColor { get; set; }

        /// <summary>
        /// Gets or sets the edges to render.
        /// </summary>
        public BorderEdge Edges { get; set; }

        /// <summary>
        /// Gets or sets the size of the border in pixel.
        /// </summary>
        public int BorderSize;

        /// <summary>
        /// Gets or sets the color of the border.
        /// </summary>
        public override Color Color
        {
            get
            {
                return color;
            }
            set
            {
                color = value;
            }
        }


        #endregion
        #region methods

        public override void Render(Renderer renderer)
        {
            if (vectorSize != Size) vectors = null;
            if (vectors == null) vectors = CreateVectors();

            gl.Disable(Capability.Texture2D);
            gl.DisableClientState(ClientStateArray.TextureCoord);

            Color c = UseTextColor? renderer.TextColor: this.color;
            GlColor color = GlColor.FromColor(c);
            gl.Color4x(color.R << 8, color.G << 8, color.B << 8, color.A * renderer.Alpha);
            gl.VertexPointer(vectors);
            gl.CheckError();
            gl.DrawArrays(PrimitiveType.Triangles, 0, vectors.Length);
            gl.CheckError();
            gl.EnableClientState(ClientStateArray.TextureCoord);
            gl.CheckError();
            gl.Enable(Capability.Texture2D);

        }

        private Vector2s[] CreateVectors()
        {

            int num = GetNumEdges();
            Vector2s[] vectors = new Vector2s[6 * num];

            Size size = Size;
            int w = size.Width;
            int h = size.Height;
            int bs = BorderSize;

            BorderEdge edges = Edges;

            int index = 0;
            int bst = ((edges & BorderEdge.Top) != 0) ? bs : 0;
            int bsb = ((edges & BorderEdge.Bottom) != 0) ? bs : 0;
            if ((edges & BorderEdge.Top) != 0) CreateRectangle(0, 0, w, bs, vectors, index++);
            if ((edges & BorderEdge.Left) != 0) CreateRectangle(0, bsb, bs, h - bsb - bst, vectors, index++);
            if ((edges & BorderEdge.Right) != 0) CreateRectangle(w - bs, bsb, bs, h - bsb - bst, vectors, index++);
            if ((edges & BorderEdge.Bottom) != 0) CreateRectangle(0, h - bs, w, bs, vectors, index);

            vectorSize = size;
            return vectors;
        }

        private int GetNumEdges()
        {
            int m = (int)Edges;
            if (m == 15) return 4;
            int n = 0;
            if ((m & 1) != 0) n++;
            if ((m & 2) != 0) n++;
            if ((m & 4) != 0) n++;
            if ((m & 8) != 0) n++;
            return n;
        }

        private void CreateRectangle(int x, int y, int w, int h, Vector2s[] vectors, int index)
        {
            if (w < 0) w = 0;
            if (h < 0) h = 0;
            index *= 6;
            vectors[index++].SetValues(x, y);
            vectors[index++].SetValues(x + w, y);
            vectors[index++].SetValues(x, y + h);

            vectors[index++].SetValues(x + w, y);
            vectors[index++].SetValues(x + w, y + h);
            vectors[index].SetValues(x, y + h);
        }

        protected override Shape CreateClone()
        {
            return new BorderShape();
        }

        protected override void Copy(Shape shape)
        {
            base.Copy(shape);
            BorderShape s = shape as BorderShape;
            s.UseTextColor = UseTextColor;
            s.Edges = Edges;
            s.BorderSize = BorderSize;
        }

        #endregion
    }
}
